#pragma once
#include <iostream>
#include <string>
#include <jsoncpp/json/json.h>

class Request
{
public:
    Request()
    {
        _x = _y = _oper = 0;
    }
    bool Serialize(std::string *out)
    {
        Json::Value root;
        root["x"] = _x;
        root["y"] = _y;
        root["oper"] = _oper;
        Json::StyledWriter writer;
        *out = writer.write(root);
        if (out->empty())
            return false;
        return true;
    }
    bool DeSerialize(const std::string &in)
    {
        Json::Reader reader;
        Json::Value root;
        bool ret = reader.parse(in, root);
        if (!ret)
            return false;
        _x = root["x"].asInt();
        _y = root["y"].asInt();
        _oper = root["oper"].asInt();

        return true;
    }
    ~Request() {}

private:
    int _x;
    int _y;
    int _oper;
};

class Response
{
public:
    Response() : _result(0), _code(0)
    {
    }
    bool Serialize(std::string *out)
    {
        Json::Value root;
        root["result"] = _result;
        root["code"] = _code;
        Json::StyledWriter writer;
        *out = writer.write(root);
        if (out->empty())
            return false;
        return true;
    }
    bool DeSerialize(const std::string &in)
    {
        Json::Reader reader;
        Json::Value root;
        bool ret = reader.parse(in, root);
        if (!ret)
            return false;
        _result = root["result"].asInt();
        _code = root["code"].asInt();

        return true;
    }
    ~Response() {}

private:
    int _result;
    int _code;
};

const static std::string sep = "\r\n";

class Protocol
{
public:
    Protocol() {}
    static std::string Package(const std::string &jsonstr)
    {
        if (jsonstr.empty())
            return std::string();
        std::string json_len = std::to_string(jsonstr.size());
        return json_len + sep + jsonstr + sep;
    }
    static bool DigitSafeCheck(const std::string str)
    {
        for (int i = 0; i < str.size(); i++)
        {
            if (!(str[i] >= '0' && str[i] <= '9'))
                return false;
        }
        return true;
    }
    static int Unpack(std::string &orgin_str, std::string *package)
    {
        auto pos = orgin_str.find(sep);
        if (pos == std::string::npos)
        {
            return 0;
        }
        std::string len_str = orgin_str.substr(0, pos);
        if (!DigitSafeCheck(len_str))
        {
            return -1;
        }
        int digit_len = std::stoi(len_str);
        int target_len = digit_len + len_str.size() + 2 * sep.size();
        if (target_len > orgin_str.size())
            return 0;
        *package = orgin_str.substr(pos + sep.size(), digit_len);
        orgin_str.erase(0, target_len);
        return package->size();
    }
    ~Protocol() {}

private:
};